<!DOCTYPE html>
<html lang="zh-cn">


<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1.0, user-scalable=no">
  <meta name="theme-color" content="#202020"/>
  <meta http-equiv="x-ua-compatible" content="ie=edge">
  
  
    <meta name="keywords" content="zookeeper," />
  

  
    <meta name="description" content="我在时间的长河中流浪，寻找一个有你的地方" />
  
  
  
    <link rel="icon" type="image/x-icon" href="https://cdn.jsdelivr.net/gh/haige2486/CDN@1.0/images/favicon.ico">
  
  <title>Zookeeper自学笔记 [ 海哥のBlog ]</title>
  
    <!-- stylesheets list from config.yml -->
    
      <link rel="stylesheet" href="//cdn.bootcss.com/pure/1.0.0/pure-min.css">
    
      <link rel="stylesheet" href="/css/xoxo.css">
    
      <link rel="stylesheet" href="/css/keyframe.css">
    
  
  <script src="https://cdn.jsdelivr.net/npm/pjax/pjax.js"></script>
  <script async src="https://busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>
<meta name="generator" content="Hexo 4.2.0"></head>

<body>
  <div class="nav-container">
    <nav class="home-menu pure-menu pure-menu-horizontal">
  <a class="pure-menu-heading" href="/">
    
      <img class="avatar" src="https://cdn.jsdelivr.net/gh/haige2486/CDN@1.0/images/custom/avatar.png">
    
    <span class="title">海哥のBlog</span>
  </a>

  <ul class="pure-menu-list clearfix">
      
          
            <li class="pure-menu-item"><a href="/" class="pure-menu-link">首页</a></li>
          
      
          
            <li class="pure-menu-item"><a href="/archives" class="pure-menu-link">归档</a></li>
          
      
          
            <li class="pure-menu-item"><a href="/tags" class="pure-menu-link">标签</a></li>
          
      
          
            <li class="pure-menu-item"><a href="/categories" class="pure-menu-link">分类</a></li>
          
      
          
            <li class="pure-menu-item"><a href="/search" class="pure-menu-link">搜索</a></li>
          
      
  </ul>
   
</nav>
  </div>

  <div class="container" id="content-outer">
    <div class="inner" id="content-inner">
      <div class="post-container">
  <article class="post" id="post">
    <header class="post-header text-center">
      <h1 class="title">
        Zookeeper自学笔记
      </h1>
      <span>
        
        <time class="time" datetime="2020-04-05T12:08:45.000Z">
          2020-04-05
        </time>
        
      </span>
      
      <span class="slash">/</span>
      <span class="post-meta">
        <span class="post-tags">
          <ul class="article-tag-list" itemprop="keywords"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/zookeeper/" rel="tag">zookeeper</a></li></ul>
        </span>
      </span>
      
      <span class="slash">/</span>
      <span class="read" span id="busuanzi_container_page_pv">
        本文总阅读量：<span id="busuanzi_value_page_pv"></span>次
      </span>
    </header>

    <div class="post-content">
      <h1 id="什么是zookeeper"><a href="#什么是zookeeper" class="headerlink" title="什么是zookeeper"></a>什么是zookeeper</h1><p><a href="https://zookeeper.apache.org/" target="_blank" rel="noopener">Zookeeper</a>是一个分布式协调服务，可用于服务发现，分布式锁，分布式领导选举，配置管理等。</p>
<p>这一切的基础，都是Zookeeper提供了一个类似于Linux文件系统的树形结构（可认为是轻量级的内存文件系统，其每个节点znode下只能存1M数据，即不要当数据库使用），同时提供了对于每个节点的监控与通知机制。</p>
<p>知识点：</p>
<ol>
<li>由于zookeeper是分布式集群服务，因此要考虑如何保证数据的一致性的。</li>
<li>由于zookeeper是基于内存的，速度快，断电易失，所以要持久化处理。</li>
<li>由于zookeeper是主从复制集群，主为单点（考虑单点故障、单点容量、单点压力），所以考虑HA高可用。</li>
<li>完成分布式协调其实是很困难的，可以引入分布式锁。</li>
</ol>
<h2 id="zookeeper结构模型"><a href="#zookeeper结构模型" class="headerlink" title="zookeeper结构模型"></a>zookeeper结构模型</h2><ol>
<li>Zookeeper集群是一个基于主从复制的高可用集群，每个服务器承担如下三种角色中的一种</li>
</ol>
<ul>
<li><p><strong>Leader</strong> 一个Zookeeper集群同一时间只会有一个实际工作的Leader，它会发起并维护与各Follwer及Observer间的心跳。所有的写操作必须要通过Leader完成再由Leader将写操作广播给其它服务器。</p>
</li>
<li><p><strong>Follower</strong> 一个Zookeeper集群可能同时存在多个Follower，它会响应Leader的心跳。Follower可直接处理并返回客户端的读请求，同时会将写请求转发给Leader处理，并且负责在Leader处理写请求时对请求进行投票。</p>
</li>
<li><p><strong>Observer</strong> 角色与Follower类似，但是无投票权。</p>
<p>因为leader节点肯定会出现不可用情况，所以zookeeper集群有两种状态，即：可用状态（主从复制集群）与不可用状态（无主模型），由官网数据其能在200ms内恢复。</p>
<p>因为集群中参与选举的节点越多，其选举时间越长，所以在该集群中应保证高可用情况下follower最少，其余设置为observer。</p>
<p>因为集群中只有leader有写权限，所以zookeeper的读取能力快于写入能力。</p>
</li>
</ul>
<ol>
<li><p>zookeeper是一种目录树结构，其中每个节点znode可存数据为1M，节点可按如下两个维度分类：</p>
<ul>
<li>Persist（永久节点） vs. Ephemeral（临时节点）<ul>
<li><strong>Persist</strong>节点，一旦被创建，便不会意外丢失，即使服务器全部重启也依然存在。每个 Persist 节点即可包含数据，也可包含子节点</li>
<li><strong>Ephemeral</strong>节点，在创建它的客户端与服务器间的 Session 结束时自动被删除。服务器重启会导致 Session 结束，因此 Ephemeral 类型的 znode 此时也会自动删除</li>
</ul>
</li>
<li>Sequence（序列节点） vs. Non-sequence（非序列节点）<ul>
<li><strong>Non-sequence</strong>节点，多个客户端同时创建同一 Non-sequence 节点时，只有一个可创建成功，其它匀失败。并且创建出的节点名称与创建时指定的节点名完全一样</li>
<li><strong>Sequence</strong>节点，创建出的节点名在指定的名称之后带有10位10进制数的序号。多个客户端创建同一名称的节点时，都能创建成功，只是序号不同，其序号由zookeeper服务维护</li>
</ul>
</li>
</ul>
</li>
<li><p>当zookeeper客户端连接到zookeeper服务上时，其间是通过session来保持会话的，每次连接与断开都会消耗zookeeper的zxid(事务id)，session存在集群每个节点中，类似ephemeral。</p>
<p>在做分布式协调时，redis集群为减少对数据库连接而创建锁，让一个线程去将数据库取回数据更新缓存，而其他线程处于等待状态，由于锁的存在增加了客户端的复杂度，其他线程不知道占用锁的线程挂掉而阻塞，如设置过期时间，又会在占锁线程未完成时重新竞争锁，导致重复阻塞，只能引入守护线程。由于session的存在，zookeeper与redis不同，其客户端与服务连接状态存于session中，session就能代表其唯一性，利用这点与ephemeral+sequence技术可实现分布式锁。</p>
</li>
</ol>
<p><img src="/images/ZOOKEEPER.jpg" alt="ZOOKEEPER"></p>

    </div>

    <div>全文完。</div>
  </article>
  <div class="toc-container">
    
  <div id="toc" class="toc-article">
    <strong class="toc-title">目录</strong>
    <ol class="toc"><li class="toc-item toc-level-1"><a class="toc-link" href="#什么是zookeeper"><span class="toc-text">什么是zookeeper</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#zookeeper结构模型"><span class="toc-text">zookeeper结构模型</span></a></li></ol></li></ol>
  </div>


  </div>
</div>

<div class="share" style="width: 100%;">
  <div class="text-center">
    人生若只如初见，何事秋风悲画扇。
  </div> 
</div>

  
    <div class="post-nav">
      <div class="post-nav-item post-nav-next">
        
      </div>
  
      <div class="post-nav-item post-nav-prev">
          
          <a href="/2020/04/05/windows-os-%E5%88%9B%E5%BB%BAwifi%E7%83%AD%E7%82%B9/" rel="prev" title="windows os 创建wifi热点">
            windows os 创建wifi热点
          </a>
          <span>〉</span>
        
      </div>
    </div>
  

    </div>

    
    <div id="toTop">^</div>
  </div>
  <footer class="footer text-center">
    <div id="bottom-inner">
        <a class="bottom-item" href="https://lustghost.gitee.io">首页</a> |
        <a class="bottom-item" href="https://github.com/haige2486" target="_blank">GitHub</a> |
        <a class="bottom-item" href="https://hexo.io" target="_blank">Powered by hexo</a>
    </div>
</footer>
  

<script>
  var pjax = new Pjax({
    elements: "a",
    selectors: [".inner"]
  });

  document.addEventListener('visibilitychange', function () {
    if (document.visibilityState == 'hidden') {
      normal_title = document.title;
      document.title = 'დ待゜人归ꦿ໊ོﻬ࿐ོ';
    } else document.title = normal_title;
  });

  function rt() {
    var d = document,
      dd = document.documentElement,
      db = document.body,
      top = dd.scrollTop || db.scrollTop,
      step = Math.floor(top / 20);
    (function () {
      top -= step;
      if (top > -step) {
        dd.scrollTop == 0 ? db.scrollTop = top : dd.scrollTop = top;
        setTimeout(arguments.callee, 20);
      }
    })();
  }
  document.getElementById("toTop").addEventListener("click", rt);
  document.addEventListener("scroll", function () {
    var dd = document.documentElement,
      db = document.body,
      top = dd.scrollTop || db.scrollTop
    if (top > (window.innerHeight*0.7)) {
      document.getElementById("toTop").style.display = "block";
      document.getElementsByClassName("nav-container")[0].style.display = "none";
    } else {
      document.getElementById("toTop").style.display = "none";
    }
    if(top<50){
      document.getElementsByClassName("nav-container")[0].style.display = "block";
    }
  })
</script>
  



  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/aplayer/dist/APlayer.min.css">
<script src="https://cdn.jsdelivr.net/npm/aplayer/dist/APlayer.min.js"></script>
<!-- require MetingJS -->
<script src="https://cdn.jsdelivr.net/npm/meting@2/dist/Meting.min.js"></script>
<meting-js  id="2660651585"  server="netease"  type="playlist"  fixed="true"  autoplay="false"  loop="all"  order="random"  preload="auto"  volume="0.7"  mutex="true"  </meting-js>
    <style id="rewrite">
        .aplayer.aplayer-fixed{
            width: 70%;
        }
        .aplayer-body{
            width: 80% !important;
        }
        .aplayer.aplayer-narrow .aplayer-body {
            left: -66px !important;
        }
        .aplayer.aplayer-fixed .lrc-show {
            display: block;
            background: rgba(255, 255, 255, 0.8);
        }
        .aplayer-lrc-current{
            animation: shake-it .5s reverse infinite cubic-bezier(0.68, -0.55, 0.27, 1.55);
        }
    </style>
    <script>
        typeof document.getElementsByClassName("aplayer")[0] !== "undefined" && document.getElementsByClassName("aplayer")[0].addEventListener("click", function () {
            if (document.getElementsByClassName("aplayer-button")[0].hasClass('aplayer-play')) {
                document.getElementsByClassName('aplayer-lrc')[0].removeClass('lrc-show');
            } else {
                document.getElementsByClassName('aplayer-lrc')[0].addClass('lrc-show');
            }
        })
    </script>
</body>
</html>
